
from .sessionInfo import SessionInfo
from abc import ABC, abstractmethod

class BaseGraphNode(ABC):
    def __init__(self, id:str, data:dict, graphNodeManager ,random_key:str):
        from managers.graphNodeManager import GraphNodeManager
        self.id = id
        self.data = data
        assert isinstance(graphNodeManager, GraphNodeManager), "graphNodeManager must be an instance of GraphNodeManager"
        self.graphNodeManager = graphNodeManager
        self.random_key = random_key
        self.name = data['data']['name']
        self.type = data['type']
        self.dict = {'in':{}, 'out':{}} #'out' :{sessionInfo.id:{ targethandle:[output_1, output_2] }}
        self.executed_num = 0
        self.flow_next_nodes = []
        

    def execute(self, session_info: SessionInfo=None):
        pass

    # 将默认实现直接放在基类中
    def add_flow_next(self, node_id:str, **kwargs):
        """添加 flow_next_nodes。
        如果重写此方法，必须同时重写 get_all_flow_next_nodes。
        """
        self.flow_next_nodes.append(node_id)

    def get_all_flow_next_nodes(self): 
        """获取所有 flow_next_nodes。
        如果重写此方法，必须同时重写 add_flow_next。
        """
        return self.flow_next_nodes

    @classmethod
    def __init_subclass__(cls, **kwargs):
        super().__init_subclass__(**kwargs)
        has_add = 'add_flow_next' in cls.__dict__
        has_get = 'get_all_flow_next_nodes' in cls.__dict__
        if has_add != has_get:
            raise TypeError(
                f"Class {cls.__name__} must override both add_flow_next and "
                f"get_all_flow_next_nodes methods together, or none of them."
            )
    
    def flow_next(self, session_info: SessionInfo):
        """将下一个节点添加到执行队列中"""
        for node_id in self.flow_next_nodes:
            # 更新执行次数
            session_info.flow_prev_nodes_executed_number[node_id][self.id] += 1
            # 检查是否所有前置节点都已执行相同次数
            self.graphNodeManager.add_to_execution_queue(node_id, session_info)

    def get_newest_output_in_session(self, session_info: SessionInfo, target_handle: str):
        if target_handle in self.dict['out'][session_info.id]:
            return self.dict['out'][session_info.id][target_handle][-1]
        else:
            return None
        
    def stop(self):
        pass